package com.miyu.system.utils.crawler.book;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.miyu.plugins.utils.GetBeanUtil;
import com.miyu.system.pojo.crawler.BookPageVo;
import com.miyu.system.pojo.system.SysRule;
import com.miyu.system.utils.crawler.CrawlerUtils;
import net.dreamlu.mica.redis.cache.MicaRedisCache;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.selector.Selectable;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class CommonBookJx {
    static MicaRedisCache redisCache = GetBeanUtil.getBeanByClass(MicaRedisCache.class);

    /**
     * 图书搜索
     * 搜索解析
     * @param page 页面
     * @throws Exception 异常
     */
    public static void bookSearch(Page page) throws Exception {

        //当前url连接
        String url = page.getRequest().getUrl();
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        //缓存key
        String key = bpv.getKey();

        /* 取出当前实体*/
        SysRule sysRule = redisCache.get("system:sysRule:"+bpv.getRuleId());
        //获取当前页搜索规则
        JSONObject rule = JSONObject.parseObject(sysRule.getRuleSet()).getJSONObject(bpv.getOperate());
        //固定值不可改变 bookList
        List<Selectable> list = JXPageUtils.JXPageRuleByPage(page,rule.getString("bookList"));
        JSONObject showTitle = rule.getJSONObject("showTitle");
        JSONArray ja = new JSONArray();
        for (Selectable stable : list) {
            JSONObject jo = new JSONObject();
            for (Map.Entry entry : showTitle.entrySet()) {
                String v = entry.getValue().toString();
                String k = entry.getKey().toString();
                if (!v.trim().isEmpty()) {
                    if (key.indexOf("!") > 0) {
                        //#做数据分割可做动态表头查询数据 以及取值数据扩展
                        String value = JXPageUtils.JXPageRuleByTable(stable, v);
                        if (StrUtil.isNotBlank(value)) {
                            jo.put(k.substring(0, k.indexOf("!")), value);
                        }
                    } else {
                        String value = JXPageUtils.JXPageRuleByTable(stable, v);
                        if (StrUtil.isNotBlank(value)) {
                            jo.put(k, value);
                        }
                    }
                }
            }
            if (!jo.isEmpty()) {
                ja.add(jo);
            }
        }
        bpv.getData().put(BookOperate.BOOK_SEARCH.getCode(), ja);
        redisCache.setEx(bpv.getKey(),bpv,bpv.getTimeout(), TimeUnit.SECONDS);

    }

    /**
     * 书籍详情
     * 根据url获取书籍详情数据
     * 同时获取章节目录链接
     * @param page 页
     * @throws Exception 例外
     */
    public static void bookDetail(Page page) throws Exception {
        String url = page.getRequest().getUrl();
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        /* 取出当前实体*/
        SysRule sysRule = redisCache.get("system:sysRule:"+bpv.getRuleId());
        //获取当前页搜索规则
        JSONObject rule = JSONObject.parseObject(sysRule.getRuleSet()).getJSONObject(bpv.getOperate());
        JSONObject jo = new JSONObject();
        jo.put("bookUrl",url);
        // 固定值不可改变 bookList
        Selectable selectable=null;

        if(StrUtil.isNotBlank(rule.getString("bookBox"))){
            selectable = JXPageUtils.JXPageRuleByPage(page,rule.getString("bookBox")).get(0);
        }else{
            /** 当前根页面*/
            selectable = page.getHtml().xpath("//body");
        }


        JSONObject detail = rule.getJSONObject("bookDetail");
        for (Map.Entry entry : detail.entrySet()) {
            String v = entry.getValue().toString();
            String k = entry.getKey().toString();
            if (!v.trim().isEmpty()) {
                jo.put(k,JXPageUtils.JXPageRuleByTable(selectable,v));
            }
        }
        //需要在明细页面获取章节列表链接 提取菜单
        bpv.getData().put(BookOperate.BOOK_DETAIL.getCode(), jo);
        /*数据收集时不清除缓存*/
        if(bpv.getKey().indexOf("collect")>0)
            redisCache.set(bpv.getKey(),bpv);
        else
            redisCache.setEx(bpv.getKey(),bpv,bpv.getTimeout(), TimeUnit.SECONDS);
    }



    /**
     * 章节解析
     * @param page
     * @throws Exception
     */
    public static void bookChapter(Page page) throws Exception {
        /**当前url连接*/
        String url = page.getRequest().getUrl();
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        //缓存key
        String key = bpv.getKey();
        /* 取出当前实体*/
        SysRule sysRule = redisCache.get("system:sysRule:"+bpv.getRuleId());
        //获取当前页搜索规则
        JSONObject rule = JSONObject.parseObject(sysRule.getRuleSet()).getJSONObject(bpv.getOperate());
        /**明细规则*/
        //书籍章节取值 独立只取章节
        String bc = rule.getString("bookChapterList");
        List<Selectable> chapterlist = JXPageUtils.JXPageRuleByPage(page,bc);
        JSONObject chapterInfo = rule.getJSONObject("bookChapterInfo");
        JSONArray ja = new JSONArray();
        for (int i=0;i<chapterlist.size();i++){
            Selectable stable = chapterlist.get(i);
            JSONObject jo = new JSONObject();
            for (Map.Entry entry : chapterInfo.entrySet()) {
                String v = entry.getValue().toString();
                if(!v.trim().isEmpty()){
                    //加入规则Id
                    jo.put("ruleId",bpv.getRuleId());
                    //增加排序
                    jo.put("num",i+1);
                    //判断是否是末级处理
                    jo.put(entry.getKey().toString(), JXPageUtils.JXPageRuleByTable(stable, v));
                }
            }
            ja.add(jo);
        }
        bpv.getData().put(BookOperate.BOOK_CHAPTER.getCode(), ja);
        /*数据收集时不清除缓存*/
        if(bpv.getKey().indexOf("collect")>0)
            redisCache.set(bpv.getKey(),bpv);
        else
            redisCache.setEx(bpv.getKey(),bpv,bpv.getTimeout(), TimeUnit.SECONDS);
    }

    /**
     * 图书阅读器
     * 阅读页面
     * @param page 页
     * @throws Exception 例外
     */
    public static void bookReader(Page page) throws Exception {
        /**当前url连接*/
        String url = page.getRequest().getUrl();
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        //缓存key
        String key = bpv.getKey();
        /* 取出当前实体*/
        SysRule sysRule = redisCache.get("system:sysRule:"+bpv.getRuleId());
        //获取当前页搜索规则
        JSONObject rule = JSONObject.parseObject(sysRule.getRuleSet()).getJSONObject(bpv.getOperate());
        //解析临时数据

        JSONObject jo = new JSONObject();
        Selectable selectable=null;
        if(StrUtil.isNotBlank(rule.getString("readBox"))){
            selectable = JXPageUtils.JXPageRuleByPage(page,rule.getString("readBox")).get(0);
        }else{
            /*当前页面*/
            selectable = page.getHtml().xpath("//body");
        }
        JSONObject bookReadBox = rule.getJSONObject("bookReadBox");
        jo.put("contextUrl",url);
        jo.put("ruleId",bpv.getRuleId());
        for (Map.Entry entry : bookReadBox.entrySet()) {
            String v = entry.getValue().toString();
            if(!v.trim().isEmpty()){
                jo.put(entry.getKey().toString(), JXPageUtils.JXPageRuleByTable(selectable, v));
            }
        }
        //需要在明细页面获取章节列表链接 提取菜单
        JSONArray ja = new JSONArray();
        ja.add(jo);
        bpv.getData().put(BookOperate.BOOK_READER.getCode(), ja);
        /*数据收集时不清除缓存*/
        if(bpv.getKey().indexOf("collect")>0)
            redisCache.set(bpv.getKey(),bpv);
        else
            redisCache.setEx(bpv.getKey(),bpv,bpv.getTimeout(), TimeUnit.SECONDS);

    }

    /**
     * 收集书籍
     * 书籍采集
     * @param page 页面
     * @throws Exception 例外
     */
    public static void collectBook (Page page)  throws Exception {
        /**当前url连接*/
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        bookDetail(page);

        BookPageVo pv = redisCache.get(bpv.getKey());
        JSONObject bookInfo = pv.getData().getJSONArray(BookOperate.BOOK_DETAIL.getCode()).getJSONObject(0);
        String url = bookInfo.getString("tocUrl");//章节链接 固定字段

        /* 取出当前实体*/
        SysRule s = redisCache.get("system:sysRule:"+pv.getRuleId());
        JSONObject rule= null;
        if (s != null) {
            rule = JSONObject.parseObject(s.getRuleSet()).getJSONObject(BookOperate.BOOK_CHAPTER.getCode());
        }
        pv.setOperate(BookOperate.BOOK_CHAPTER.getCode());
        page.getRequest().putExtra("params",pv);
        page.getRequest().setUrl(url);
        page.addTargetRequest(page.getRequest());
        pv = redisCache.get(bpv.getKey());
    }

    /**
     * 检查规则
     * @param page 页
     * @throws Exception 例外
     */
    public static void checkRule(Page page)  throws Exception{
        //当前url连接
        String url = page.getRequest().getUrl();
        //参数
        BookPageVo bpv= page.getRequest().getExtra("params");
        //缓存key
        String key = bpv.getKey();
        /* 取出当前实体*/
        SysRule sysRule = redisCache.get("system:sysRule:"+bpv.getRuleId());
        //获取当前页搜索规则
        JSONObject rule = JSONObject.parseObject(sysRule.getRuleSet()).getJSONObject(bpv.getOperate());
        JSONObject jo = new JSONObject();
        jo.put("checkValue",JXPageUtils.JXPageRuleByCheckRule(page,rule.getString("checkValue")));
        bpv.getData().put(BookOperate.CHECKRULE.getCode(), jo);
        redisCache.set(CrawlerUtils.REDIS_CACHE_BOOK+key,bpv);
    }

}
